// Copyright (C) Asobo Studio. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. // based on the w32api implementation of the GDI+ wrappers: // // Created by Markus Koenig #ifndef __GDIPLUS_HEADERS_H #define __GDIPLUS_HEADERS_H #include #include #include "GdiPlus.h" #include "gdiplusflat.h" namespace Gdiplus { /* * Note: Virtual inline functions (dtors, Clone()) are implemented here: If * these were defined outside class scope, the compiler would always generate * code for them (and the vtable), even if these classes were never used. */ class Bitmap; class Effect; class FontCollection; class FontFamily; class Graphics; class GraphicsPath; class Matrix; class Pen; //typedef void IStream; //The use of streams ins not supported by the underlying implementation //typedef void ImageItemData; //typedef void IDirectDrawSurface7; class Image : public GdiplusBase { friend class Bitmap; friend class Metafile; friend class CachedBitmap; friend class Graphics; friend class TextureBrush; public: static Image* FromFile(const WCHAR* filename, BOOL useEmbeddedColorManagement = FALSE); //static Image* FromStream(IStream *stream, // BOOL useEmbeddedColorManagement = FALSE); Image(const WCHAR* filename, BOOL useEmbeddedColorManagement = FALSE); //Image(IStream *stream, BOOL useEmbeddedColorManagement = FALSE); virtual ~Image() { DLLExports::GdipDisposeImage(nativeImage); } virtual Image* Clone() const { GpImage* cloneImage = NULL; Status status = updateStatus(DLLExports::GdipCloneImage( nativeImage, &cloneImage)); if (status == GpStatus::Ok) { Image* result = new Image(cloneImage, lastStatus); if (!result) { DLLExports::GdipDisposeImage(cloneImage); lastStatus = OutOfMemory; } return result; } else { return NULL; } } //Status FindFirstItem(ImageItemData *item); //Status FindNextItem(ImageItemData *item); Status GetAllPropertyItems(UINT totalBufferSize, UINT numProperties, PropertyItem* allItems); Status GetBounds(RectF* srcRect, Unit* srcUnit); Status GetEncoderParameterList(const CLSID* clsidEncoder, UINT size, EncoderParameters* buffer); UINT GetEncoderParameterListSize(const CLSID* clsidEncoder); UINT GetFlags(); UINT GetFrameCount(const GUID* dimensionID); UINT GetFrameDimensionsCount(); Status GetFrameDimensionsList(GUID* dimensionIDs, UINT count); UINT GetHeight(); REAL GetHorizontalResolution(); //Status GetItemData(ImageItemData *item); Status GetPalette(ColorPalette* palette, INT size); INT GetPaletteSize(); Status GetPhysicalDimension(SizeF* size); PixelFormat GetPixelFormat(); UINT GetPropertyCount(); Status GetPropertyIdList(UINT numOfProperty, PROPID* list); Status GetPropertyItem(PROPID propId, UINT propSize, PropertyItem* buffer); UINT GetPropertyItemSize(PROPID propId); Status GetPropertySize(UINT* totalBufferSize, UINT* numProperties); Status GetRawFormat(GUID* format); Image* GetThumbnailImage(UINT thumbWidth, UINT thumbHeight, GetThumbnailImageAbort callback, VOID* callbackData); ImageType GetType() const; REAL GetVerticalResolution(); UINT GetWidth(); Status RemovePropertyItem(PROPID propId); Status RotateFlip(RotateFlipType rotateFlipType); //Status Save(IStream *stream, const CLSID *clsidEncoder, // const EncoderParameters *encoderParams); Status Save(const WCHAR* filename, const CLSID* clsidEncoder, const EncoderParameters* encoderParams); Status SaveAdd(const EncoderParameters* encoderParams); Status SaveAdd(Image* newImage, const EncoderParameters* encoderParams); Status SelectActiveFrame(const GUID* dimensionID, UINT frameIndex); Status SetAbort(GdiplusAbort* pIAbort); Status SetPalette(const ColorPalette* palette); Status SetPropertyItem(const PropertyItem* item); Status GetLastStatus() const { Status result = lastStatus; lastStatus = Ok; return result; } private: Image(GpImage* image, Status status) : nativeImage(image), lastStatus(status) {} Image(const Image&); Image& operator=(const Image&); Status updateStatus(Status newStatus) const { if (newStatus != GpStatus::Ok) lastStatus = newStatus; return newStatus; } GpImage* nativeImage; mutable Status lastStatus; }; class Bitmap : public Image { public: //static Bitmap* FromBITMAPINFO(const BITMAPINFO* gdiBitmapInfo, // VOID* gdiBitmapData); //static Bitmap* FromDirectDrawSurface7(IDirectDrawSurface7 *surface); static Bitmap* FromFile(const WCHAR* filename, BOOL useEmbeddedColorManagement = FALSE); static Bitmap* FromHBITMAP(HBITMAP hbm, HPALETTE hpal); static Bitmap* FromHICON(HICON icon); static Bitmap* FromResource(HINSTANCE hInstance, const WCHAR* bitmapName); //static Bitmap* FromStream(IStream *stream, // BOOL useEmbeddedColorManagement = FALSE); static Status ApplyEffect(Bitmap** inputs, INT numInputs, Effect* effect, RECT* ROI, RECT* outputRect, Bitmap** output); //static Status InitializePalette(ColorPalette *palette, // PaletteType paletteType, INT optimalColors, // BOOL useTransparentColor, Bitmap *bitmap); Bitmap(const BITMAPINFO* gdiBitmapInfo, VOID* gdiBitmapData); //Bitmap(IDirectDrawSurface7 *surface); #ifdef _MSFS_WASM_PROXY_GDIPLUS Bitmap(const char* filename, BOOL useEmbeddedColorManagement); Bitmap(Graphics* graphics, const char* filename, BOOL useEmbeddedColorManagement = FALSE); Bitmap(Graphics* graphics, const WCHAR* filename, BOOL useEmbeddedColorManagement = FALSE); Status Load(Graphics* gfx); #endif Bitmap(const WCHAR* filename, BOOL useEmbeddedColorManagement = FALSE); Bitmap(HBITMAP hbm, HPALETTE hpal); Bitmap(HICON hicon); Bitmap(HINSTANCE hInstance, const WCHAR* bitmapName); //Bitmap(IStream *stream, BOOL useEmbeddedColorManagement = FALSE); Bitmap(INT width, INT height, Graphics* target); Bitmap(INT width, INT height, PixelFormat format = PixelFormat32bppARGB); Bitmap(INT width, INT height, INT stride, PixelFormat format, BYTE* scan0); virtual ~Bitmap() { } virtual Bitmap* Clone() const { #ifndef _MSFS_WASM_PROXY_GDIPLUS GpImage* cloneImage = NULL; Status status = updateStatus(DLLExports::GdipCloneImage( (GpBitmap*)nativeImage, &cloneImage)); if (status == GpStatus::Ok) { Bitmap* result = new Bitmap(cloneImage, lastStatus); if (!result) { DLLExports::GdipDisposeImage(cloneImage); lastStatus = OutOfMemory; } return result; } else { return NULL; } #else return NULL; #endif } Bitmap* Clone(const RectF& rect, PixelFormat format) const; Bitmap* Clone(const Rect& rect, PixelFormat format) const; Bitmap* Clone(REAL x, REAL y, REAL width, REAL height, PixelFormat format) const; Bitmap* Clone(INT x, INT y, INT width, INT height, PixelFormat format) const; Status ApplyEffect(Effect* effect, RECT* ROI); Status ConvertFormat(PixelFormat format, DitherType ditherType, PaletteType paletteType, ColorPalette* palette, REAL alphaThresholdPercent); Status GetHBITMAP(const Color& colorBackground, HBITMAP* hbmReturn) const; Status GetHICON(HICON* icon) const; Status GetHistogram(HistogramFormat format, UINT numberOfEntries, UINT* channel0, UINT* channel1, UINT* channel2, UINT* channel3) const; Status GetHistogramSize(HistogramFormat format, UINT* numberOfEntries) const; Status GetPixel(INT x, INT y, Color* color) const; Status LockBits(const Rect* rect, UINT flags, PixelFormat format, BitmapData* lockedBitmapData); Status SetPixel(INT x, INT y, const Color& color); Status SetResolution(REAL xdpi, REAL ydpi); Status UnlockBits(BitmapData* lcokedBitmapData); private: Bitmap(GpImage* image, Status status) : Image(image, status) {} Bitmap(const Bitmap&); Bitmap& operator=(const Bitmap&); }; class CachedBitmap : public GdiplusBase { friend class Graphics; public: CachedBitmap(Bitmap* bitmap, Graphics* graphics); ~CachedBitmap(); Status GetLastStatus() const { return lastStatus; } private: CachedBitmap(const CachedBitmap&); CachedBitmap& operator=(const CachedBitmap&); #ifndef _MSFS_WASM_PROXY_GDIPLUS GpCachedBitmapHandle nativeCachedBitmap; #endif Status lastStatus; }; class CustomLineCap : public GdiplusBase { friend class AdjustableArrowCap; friend class Pen; public: CustomLineCap(const GraphicsPath* fillPath, const GraphicsPath* strokePath, GpLineCap baseCap = LineCapFlat, REAL baseInset = 0.0f); virtual ~CustomLineCap() { DLLExports::GdipDeleteCustomLineCap(nativeCustomLineCap); } virtual CustomLineCap* Clone() const { GpCustomLineCap* cloneCustomLineCap = NULL; Status status = updateStatus(DLLExports::GdipCloneCustomLineCap( nativeCustomLineCap, &cloneCustomLineCap)); if (status == GpStatus::Ok) { CustomLineCap* result = new CustomLineCap( cloneCustomLineCap, lastStatus); if (!result) { DLLExports::GdipDeleteCustomLineCap(cloneCustomLineCap); lastStatus = OutOfMemory; } return result; } else { return NULL; } } LineCap GetBaseCap() const; REAL GetBaseInset() const; Status GetStrokeCaps(LineCap* startCap, LineCap* endCap) const; LineJoin GetStrokeJoin() const; REAL GetWidthScale() const; Status SetBaseCap(LineCap baseCap); Status SetBaseInset(REAL inset); Status SetStrokeCap(LineCap strokeCap); Status SetStrokeCaps(LineCap startCap, LineCap endCap); Status SetStrokeJoin(LineJoin lineJoin); Status SetWidthScale(REAL widthScale); Status GetLastStatus() const { Status result = lastStatus; lastStatus = Ok; return result; } private: CustomLineCap(GpCustomLineCap* customLineCap, Status status) : nativeCustomLineCap(customLineCap), lastStatus(status) {} CustomLineCap(const CustomLineCap&); CustomLineCap& operator=(const CustomLineCap&); Status updateStatus(Status newStatus) const { if (newStatus != GpStatus::Ok) lastStatus = newStatus; return newStatus; } GpCustomLineCap* nativeCustomLineCap; mutable Status lastStatus; }; class Font : public GdiplusBase { friend class Graphics; public: #ifdef _MSFS_WASM_PROXY_GDIPLUS BOOL Load(Graphics* gfx); Font(const WCHAR* familyName, const WCHAR* fontPath, REAL emSize, INT style, Unit unit = Unit::UnitPixel, const FontCollection* fontCollection = NULL); Font(const char* familyName, const char* fontPath, REAL emSize, INT style, Unit unit, const FontCollection* fontCollection); #endif Font(const FontFamily* family, REAL emSize, INT style = FontStyleRegular, Unit unit = UnitPoint); Font(HDC hdc, HFONT hfont); Font(HDC hdc, const LOGFONTA* logfont); Font(HDC hdc, const LOGFONTW* logfont); Font(HDC hdc); Font(const WCHAR* familyName, REAL emSize, INT style = FontStyleRegular, Unit unit = UnitPoint, const FontCollection* fontCollection = NULL); ~Font(); Font* Clone() const; Status GetFamily(FontFamily* family) const; REAL GetHeight(const Graphics* graphics) const; REAL GetHeight(REAL dpi) const; Status GetLogFontA(const Graphics* graphics, LOGFONTA* logfontA) const; Status GetLogFontW(const Graphics* graphics, LOGFONTW* logfontW) const; REAL GetSize() const; INT GetStyle() const; Unit GetUnit() const; Status GetLastStatus() const { return lastStatus; } BOOL IsAvailable() const { return nativeFont != NULL; } private: Font(GpFont* font, Status status) : nativeFont(font), lastStatus(status) {} Font(const Font&); Font& operator=(const Font&); Status updateStatus(Status newStatus) const { if (newStatus != GpStatus::Ok) lastStatus = newStatus; return newStatus; } GpFont* nativeFont; mutable Status lastStatus; }; class FontCollection : public GdiplusBase { friend class InstalledFontCollection; friend class PrivateFontCollection; friend class Font; friend class FontFamily; public: FontCollection(); virtual ~FontCollection() {} Status GetFamilies(INT numSought, FontFamily* families, INT* numFound) const; INT GetFamilyCount() const; Status GetLastStatus() const { return lastStatus; } private: FontCollection(const FontCollection&); FontCollection& operator=(const FontCollection&); Status updateStatus(Status newStatus) const { return lastStatus = newStatus; } GpFontCollection* nativeFontCollection; mutable Status lastStatus; }; class FontFamily : public GdiplusBase { friend class Font; friend class FontCollection; friend class GraphicsPath; public: static const FontFamily* GenericMonospace(); static const FontFamily* GenericSansSerif(); static const FontFamily* GenericSerif(); FontFamily(); FontFamily(const WCHAR* name, const FontCollection* fontCollection = NULL); ~FontFamily(); FontFamily* Clone() const; UINT16 GetCellAscent(INT style) const; UINT16 GetCellDescent(INT style) const; UINT16 GetEmHeight(INT style) const; Status GetFamilyName(WCHAR name[LF_FACESIZE], LANGID language = LANG_NEUTRAL) const; UINT16 GetLineSpacing(INT style) const; BOOL IsStyleAvailable(INT style) const; Status GetLastStatus() const { Status result = lastStatus; lastStatus = Ok; return result; } BOOL IsAvailable() const { return nativeFontFamily != NULL; } private: FontFamily(GpFontFamily* fontFamily, Status status) : nativeFontFamily(fontFamily), lastStatus(status) {} FontFamily(const FontFamily&); FontFamily& operator=(const FontFamily&); Status updateStatus(Status newStatus) const { if (newStatus != GpStatus::Ok) lastStatus = newStatus; return newStatus; } GpFontFamily* nativeFontFamily; mutable Status lastStatus; }; class InstalledFontCollection : public FontCollection { public: InstalledFontCollection(); virtual ~InstalledFontCollection() {} }; class PrivateFontCollection : public FontCollection { public: PrivateFontCollection(); virtual ~PrivateFontCollection() { DLLExports::GdipDeletePrivateFontCollection(&nativeFontCollection); } Status AddFontFile(const WCHAR* filename); Status AddMemoryFont(const VOID* memory, INT length); }; class Region : public GdiplusBase { friend class Graphics; public: static Region* FromHRGN(HRGN hrgn); Region(); Region(const RectF& rect); Region(const Rect& rect); Region(const GraphicsPath* path); Region(const BYTE* regionData, INT size); Region(HRGN hrgn); ~Region(); Region* Clone() const; Status Complement(const RectF& rect); Status Complement(const Rect& rect); Status Complement(const Region* region); Status Complement(const GraphicsPath* path); BOOL Equals(const Region* region, const Graphics* graphics) const; Status Exclude(const RectF& rect); Status Exclude(const Rect& rect); Status Exclude(const Region* region); Status Exclude(const GraphicsPath* path); Status GetBounds(RectF* rect, const Graphics* graphics) const; Status GetBounds(Rect* rect, const Graphics* graphics) const; Status GetData(BYTE* buffer, UINT bufferSize, UINT* sizeFilled) const; UINT GetDataSize() const; HRGN GetHRGN(const Graphics* graphics) const; Status GetRegionScans(const Matrix* matrix, RectF* rects, INT* count) const; Status GetRegionScans(const Matrix* matrix, Rect* rects, INT* count) const; UINT GetRegionScansCount(const Matrix* matrix) const; Status Intersect(const RectF& rect); Status Intersect(const Rect& rect); Status Intersect(const Region* region); Status Intersect(const GraphicsPath* path); BOOL IsEmpty(const Graphics* graphics) const; BOOL IsInfinite(const Graphics* graphics) const; BOOL IsVisible(REAL x, REAL y, const Graphics* graphics = NULL) const; BOOL IsVisible(INT x, INT y, const Graphics* graphics = NULL) const; BOOL IsVisible(const PointF& point, const Graphics* graphics = NULL) const; BOOL IsVisible(const Point& point, const Graphics* graphics = NULL) const; BOOL IsVisible(REAL x, REAL y, REAL width, REAL height, const Graphics* graphics = NULL) const; BOOL IsVisible(INT x, INT y, INT width, INT height, const Graphics* graphics = NULL) const; BOOL IsVisible(const RectF& rect, const Graphics* graphics = NULL) const; BOOL IsVisible(const Rect& rect, const Graphics* graphics = NULL) const; Status MakeEmpty(); Status MakeInfinite(); Status Transform(const Matrix* matrix); Status Translate(REAL dx, REAL dy); Status Translate(INT dx, INT dy); Status Union(const RectF& rect); Status Union(const Rect& rect); Status Union(const Region* region); Status Union(const GraphicsPath* path); Status Xor(const RectF& rect); Status Xor(const Rect& rect); Status Xor(const Region* region); Status Xor(const GraphicsPath* path); Status GetLastStatus() const { Status result = lastStatus; lastStatus = Ok; return result; } private: Region(GpRegion* region, Status status) : nativeRegion(region), lastStatus(status) {} Region(const Region&); Region& operator=(const Region&); Status updateStatus(Status newStatus) const { if (newStatus != GpStatus::Ok) lastStatus = newStatus; return newStatus; } GpRegion* nativeRegion; mutable Status lastStatus; }; } #endif /* __GDIPLUS_HEADERS_H */